/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */

#include "DecompressorPPM.h"
#include <Gluck.h>


namespace liba
{
namespace pictureformat
{

DecompressorPPM::DecompressorPPM(const void * data, int size):
	current_data( 0 ),
	frame_count( 0 ),
	bytes_per_pixel( 0 )
{	
	const char * current_pos = static_cast<const char *>( data );
	const char * end = current_pos + size; 
	for( ; frame_count < MAX_MIPMAP_LEVEL; ++frame_count )
	{
		if( end - current_pos  < 2 )
			return;
		if( *current_pos != 'P' || *(current_pos + 1) != '6' )
			return;

		current_pos += 2;
		current_pos = skip_whites( current_pos, end );
		if( current_pos == end )return;
					
		current_pos = converter::simple_convert( current_pos, end, sx + frame_count );
		if( !current_pos )return;
		current_pos = converter::simple_convert( current_pos, end, sy + frame_count );
		int color_val;
		current_pos = skip_whites( current_pos, end );
		if( current_pos == end )return;
		
		const char * convert_end = current_pos;
		for( ;*convert_end > ' ' && convert_end < end; ++convert_end  );
		current_pos = converter::simple_convert( current_pos, convert_end, &color_val );		
		current_pos++;
		
		if(color_val>255)
			return;
		else
			bytes_per_pixel = 3;

		int data_size = sy[frame_count] * sx[frame_count] * bytes_per_pixel;
		if( data_size < end - current_pos )
			return;
		current_pos += data_size;
		bitmap_data[frame_count] = current_pos;		
	}
}


DecompressorPPM::~DecompressorPPM()
{}

int DecompressorPPM::get_width(int frame)const
{
	return sx[frame];
}

int DecompressorPPM::get_height(int frame)const
{
	return sy[frame];
}

Format DecompressorPPM::get_best_format()const
{
	return bytes_per_pixel == 4 ? A8R8G8B8 : R8G8B8;
}

int DecompressorPPM::get_frame_count()const
{
	return frame_count;
}

void DecompressorPPM::reset(Format f, int frame)
{
	this->frame = frame;
	if( frame < 0 || frame >= frame_count )
		THROW(Gluck(__FUNCTION__, "frame does not exist"));
	desired_format = f;
	current_data = bitmap_data[frame];
///	adv_data = static_cast<const char *>( data );
///	adv_data += sizeof(BITMAPFILEHEADER);
///	adv_data += sizeof(BITMAPINFOHEADER);
}

void DecompressorPPM::unpack_scanline(void * dst)
{
	convert_scanline<B8G8R8>(desired_format, current_data, dst, get_width(frame) );
	current_data -= bytes_per_pixel * get_width(frame);
}

void DecompressorPPM::skip_scanline(int count)
{
	current_data -= count * bytes_per_pixel * get_width(frame);
}

const char * DecompressorPPM::skip_whites( const char * begin, const char * end )const
{
	do
	{
		for( ;*begin<= ' '; ++begin )
			if( begin >= end )
				return end;

		if( *begin == '#' )
		{
			for( ;*begin != 10; ++begin )
				if( begin >= end )
					return end;
		}
		else
			return begin;
	}
	while(true);
}

} // namespace pictureformat
} // namespace liba

